package com.jiliang.member.service.impl;

import com.jiliang.common.exception.Errors;
import com.jiliang.common.exception.business.LoginException;
import com.jiliang.common.exception.business.ServerServiceException;
import com.jiliang.common.exception.business.ValidationException;
import com.jiliang.common.utils.JWTUtils;
import com.jiliang.common.utils.PasswordUtil;
import com.jiliang.member.dto.MemberIndexVo;
import com.jiliang.member.entity.MemberInfo;
import com.jiliang.member.entity.MemberLogin;
import com.jiliang.member.mapper.MemberInfoMapper;
import com.jiliang.member.mapper.MemberLoginExMapper;
import com.jiliang.member.service.MemberInfoService;
import com.jiliang.member.service.MemberLoginService;
import lombok.extern.log4j.Log4j2;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;

@Log4j2
@Service
public class MemberLoginServiceImpl implements MemberLoginService {
    @Resource
    private MemberLoginExMapper memberLoginExMapper;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private MemberInfoService memberInfoService;

    @Resource
    private MemberInfoMapper memberInfoMapper;

    /**
     * 用户登录
     * @param loginName 登录账号
     * @param loginPwd  登录密码
     * @return Token值
     */
    public MemberInfo login(String loginName, String loginPwd) {

        // 获取密码输错次数
//        String errCount = stringRedisTemplate.opsForValue().get("LOGIN_ERRCOUNT:" + loginName);
//        int errNum = 0;
//        if (StringUtils.hasText(errCount)) {
//            errNum = Integer.parseInt(errCount);
//            // 超过三次则禁止登录1小时
//            if (errNum >= 3) {
//                log.info("输入密码错误3次，账号已被锁定1小时");
//                Long expire = stringRedisTemplate.opsForValue().getOperations().getExpire("LOGIN_ERRCOUNT:" + loginName + ":LOCK_TIME");
//                if (expire > 0) {
//                    throw new ServerServiceException(Errors.SYSTEM_NO_ACCESS_ERROR, "密码错误3次,账号锁定1小时,剩余时间:" + expire + "s");
//                }
//            }
//        }
        // 校验账户状态
        MemberLogin user = memberLoginExMapper.selByName(loginName);
        // 为空则账户不存在
        if (user == null) {
            throw new ServerServiceException(Errors.SYSTEM_NO_SUCH_ACCOUNT, "账户不存在");
        }
        // 匹配密码
        if (!PasswordUtil.matchesPass(loginPwd, user.getLoginPwd())) {
            throw new LoginException(Errors.SYSTEM_NO_ACCESS_ERROR, "密码错误");
        }
        return memberInfoMapper.selectByPrimaryKey(user.getBoId());
//            // 缓存登录次数
//            log.error("用户登录: 密码错误");
//            errNum = errNum + 1;
//            stringRedisTemplate.opsForValue().set("LOGIN_ERRCOUNT:" + loginName, String.valueOf(errNum));
//            if(errNum == 1){
//                stringRedisTemplate.expire("LOGIN_ERRCOUNT:" + loginName, 10, TimeUnit.MINUTES);
//            }
//            // 密码错误限制登录机制
//            if (errNum == 3) {
//                String script = "redis.call('set',KEYS[1],ARGV[1]) redis.call('expire', KEYS[1], 3600) redis.call('expire',KEYS[2], 3600) return redis.call('get', KEYS[1])";
//                ArrayList<String> list = new ArrayList<>();
//                list.add("LOGIN_ERRCOUNT:" + loginName + ":LOCK_TIME");
//                list.add("LOGIN_ERRCOUNT:" + loginName);
//                stringRedisTemplate.execute(new DefaultRedisScript<>(script, Integer.class), list, String.valueOf(errNum));
//                throw new LoginException(Errors.SYSTEM_NO_ACCESS_ERROR, "密码错误3次，账号锁定1小时");
//            }
//            throw new LoginException(Errors.SYSTEM_NO_ACCESS_ERROR, "密码错误");
//        }
        // 账户无误生成Token
//        String token = JWTUtils.generateToken(user.getBoId(), 1L, ChronoUnit.HOURS);
//        // 将用户信息存入redis中
//        stringRedisTemplate.opsForValue().set(token, user.getBoId(), 1L, TimeUnit.HOURS);
//        stringRedisTemplate.delete("LOGIN_ERRCOUNT:" + loginName);
//        return token;
    }

    /**
     * Token换取用户信息
     * @param token 令牌
     * @return 用户信息
     */
    public MemberIndexVo getUserInfo(String token) {
        String boId = JWTUtils.validateToken(token);
        String cacheId = stringRedisTemplate.opsForValue().get(token);
        // 修改为指定的用户类
        MemberIndexVo memberInfo = memberInfoService.selMemberIndexById(cacheId);
        // 获取用户类中的boId与subject进行匹配
        if (!boId.equals(cacheId)) {
            throw new ServerServiceException(Errors.SYSTEM_NO_ACCESS_ERROR, "Token绑定用户不匹配");
        }
        return memberInfo;
    }

    /**
     * 用户登出
     * @param token 令牌
     * @return success
     */
    public String logout(String token) {
        stringRedisTemplate.delete(token);
        return "success";
    }

    /**
     * 修改密码
     * @param boId  被修改用户Id
     * @param newPassword   新密码
     * @return 修改操作值
     */
    public int alterPassword(String boId, String newPassword) {
        if (StringUtils.hasText(boId)) {
            int update = memberLoginExMapper.alterPass(boId, newPassword);
            if (update > 0) {
                return update;
            } else {
                log.error("修改用户密码: 失败");
                throw new ServerServiceException(Errors.SYSTEM_UPDATE_ERROR);
            }
        }
        throw new ValidationException("参数校验异常");
    }

}
